home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The 640 MEG Shareware Studio 2
/
The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO
/
os2
/
pccts.zip
/
AUTOMATA.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-12-08
|
6KB
|
264 lines
/* Automata conversion functions for dlg version 2
*
* Will Cohen
* 8/24/90
*/
#include <stdio.h>
#include "dlg.h"
#ifdef MEMCHK
#include "trax.h"
#else
extern char *malloc();
extern char *calloc();
#endif
#define hash_list struct _hash_list_
hash_list{
hash_list *next; /* next thing in list */
dfa_node *node;
};
int dfa_allocated = 0; /* keeps track of number of dfa nodes */
dfa_node *dfa_array; /* root of binary tree that stores dfa array */
dfa_node *dfa_model_node;
hash_list *dfa_hash[HASH_SIZE]; /* used to quickly find */
/* desired dfa node */
make_dfa_model_node(width)
int width;
{
register int i;
dfa_model_node = (dfa_node*) malloc(sizeof(dfa_node)
+ sizeof(int)*width);
dfa_model_node->left = NULL;
dfa_model_node->right = NULL;
dfa_model_node->node_no = -1; /* impossible value for real dfa node */
dfa_model_node->dfa_set = 0;
dfa_model_node->alternatives = FALSE;
dfa_model_node->done = FALSE;
dfa_model_node->nfa_states = empty;
for(i = 0; i<width; i++)
dfa_model_node->trans[i] = NIL_INDEX;
}
/* finds dfa state number and returns a pointer to it */
/* right now uses binary tree to store dfa nodes */
dfa_node *index_dfa(i)
register int i;
{
dfa_node *p = dfa_array;
if (i == NIL_INDEX)
return NULL;
while((i>1) && p){
if(i & 1)
p = p->right;
else
p = p->left;
i = i>>1;
}
return p;
}
/* adds a new dfa to the binary tree and returns a pointer to it */
dfa_node *new_dfa_node(nfa_states)
set nfa_states;
{
dfa_node *p = dfa_array;
dfa_node *t;
int i,j;
i = ++dfa_allocated;
t = (dfa_node*) malloc(sizeof(nfa_node)+sizeof(int)*class_no);
*t = *dfa_model_node;
for (j=0; j<class_no; j++)
t->trans[j] = NIL_INDEX;
t->node_no = i;
t->nfa_states = set_dup(nfa_states);
while((i>3) && p){
if(i & 1)
p = p->right;
else
p = p->left;
i = i>>1;
}
if (dfa_allocated == 1)
dfa_array = t;
else if (p != NIL_INDEX){
if (i & 1)
p->right = t;
else
p->left = t;
}
else
/* error if here */
internal_error("%s(%d): missing node on binary tree\n",
__FILE__,__LINE__);
return t;
}
/* past a pointer to the start start of the nfa graph
* nfa_to_dfa convers this graph to dfa. The function returns
* a pointer to the first dfa state.
* NOTE: The function that prints out the table will have to figure out how
* to find the other dfa states given the first dfa_state and the number of dfa
* nodes allocated
*/
dfa_node *nfa_to_dfa(start)
nfa_node *start;
{
set x, t;
dfa_node *d_state, *trans_d_state;
int a;
int last_done;
if (!start) return NULL;
t = empty;
x = set_of(NFA_NO(start));
closure(&x);
/* Make x a dfa state */
d_state = dfastate(x);
last_done = DFA_NO(d_state);
do {
/* Mark dfa state x as "done" */
d_state->done = TRUE;
last_done++; /* move forward in queue */
for (a = 0; a<class_no; a++) {
/* Build an empty set */
set_free(t);
/* Add NFA states reached by a from state b */
t = reach(d_state->nfa_states,a);
/* Were any states found? */
if (!set_nil(t)) {
/* yes, compute closure */
closure(&t);
/* Make DFA state of it ... */
trans_d_state = dfastate(t);
/* And make transition x->t, labeled with a */
d_state->trans[a] = DFA_NO(trans_d_state);
d_state->alternatives = TRUE;
}
}
/* And so forth until nothing isn't done */
d_state = DFA(last_done);
} while (last_done<=dfa_allocated);
/* returns pointer to the array that holds the automaton */
return dfa_array;
}
clear_hash()
{
register int i;
for(i=0; i<HASH_SIZE; i++)
dfa_hash[i] = 0;
}
/* Returns a pointer to a dfa node that has the same nfa nodes in it.
* This may or maynot be a newly created node.
*/
dfa_node *dfastate(nfa_states)
set nfa_states; /* list of nfa states it could be */
{
int bin;
hash_list *p;
/* hash using set and see if it exists */
bin = set_hash(nfa_states,HASH_SIZE);
p = dfa_hash[bin];
while(p && !set_equ(nfa_states,(p->node)->nfa_states)){
p = p->next;
}
if(!p){
/* next state to add to hash table */
p = (hash_list*)malloc(sizeof(hash_list));
p->node = new_dfa_node(nfa_states);
p->next = dfa_hash[bin];
dfa_hash[bin] = p;
}
return (p->node);
}
/* this reach assumes the closure has been done already on set */
set reach(b,a)
set b;
register int a;
{
register unsigned int *t,*e;
nfa_node *node;
set temp;
temp = set_of(nil);
t = e = set_pdq(b);
while (*e != nil){
node = NFA(*e);
if (set_el(a,node->label))
set_orel(NFA_NO(node->trans[0]),&temp);
e++;
}
free(t);
return temp;
}
/* finds all the nodes that can be reached by epsilon transitions
from the set of a nodes and returns puts them back in set b */
set closure(b)
set *b;
{
register nfa_node *node,*n; /* current node being examined */
unsigned *t,*e;
++operation_no;
t = e = set_pdq(*b);
while (*e != nil){
node = NFA(*e);
/* mark it done */
node->nfa_set = operation_no;
if ((n=node->trans[0]) != NIL_INDEX && set_nil(node->label) &&
(n->nfa_set != operation_no)){
/* put in b */
set_orel(NFA_NO(n),b);
close1(n,operation_no,b);
}
if ((n=node->trans[1]) != NIL_INDEX &&
(n->nfa_set != operation_no)){
/* put in b */
set_orel(NFA_NO(node->trans[1]),b);
close1(n,operation_no,b);
}
e++;
}
free(t);
return *b;
}
close1(node,o,b)
nfa_node *node;
int o; /* marker to avoid cycles */
set *b;
{
register nfa_node *n; /* current node being examined */
/* mark it done */
node->nfa_set = o;
if ((n=node->trans[0]) != NIL_INDEX && set_nil(node->label) &&
(n->nfa_set != o)){
/* put in b */
set_orel(NFA_NO(n),b);
close1(n,o,b);
}
if ((n=node->trans[1]) != NIL_INDEX &&
(n->nfa_set != o)){
/* put in b */
set_orel(NFA_NO(node->trans[1]),b);
close1(n,o,b);
}
}